/*
 * Copyright 2006-2008 Michele Mostarda ( michele.mostarda@gmail.com ).
 * All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.graphnav.model;

import org.graphnav.model.event.GraphModelListener;
import org.graphnav.swing.Arc;
import org.graphnav.swing.Node;

import java.util.Iterator;

/**
 * Defines a generic model for a <code>GraphPanel</code>
 *
 * @see org.graphnav.swing.GraphPanel
 */
public interface GraphModel {

    /**
     * Notifies that a visit of the model elements is starting,
     * no modifications of the model are allowed until the endVisit has not been reached.
     *
     * @see GraphModel#endVisit
     */
    public void startVisit();

    /**
     * Notifies that a visit of the model elements was terminated.
     * @see org.graphnav.model.GraphModel#startVisit() 
     */
    public void endVisit();

    /**
     * Returns an iterator on the model nodes.
     *
     *  @return
     */
    public Iterator<Node> nodes();

    /**
     * Returns an iterator on the model arcs.
     *
     * @return
     */
    public Iterator<Arc> arcs();

    /**
     * Returns the model node at position i-th
     * The model nodes are not ordered but they can be enumerated
     * and obtained one by one with a progressive counter.
     * The number of nodes present in the model is given by method
     * <code>nodesCount</code>.
     *
     * @param i
     * @return
     * @see GraphModel#nodesCount()
     */
    public Node getNode(int i);

    /**
     * Returns the number of nodes in the model.
     * @return
     */
    public int nodesCount();

    /**
     * Returns the model arc at position i-th
     * The model arcs are not ordered but they can be enumerated
     * and obtained one by one with a progressive counter.
     * The number of arcs present in the model is given by method
     * <code>arcsCount</code>.
     *
     * @param i
     * @return
     * @see GraphModel#arcsCount() 
     */
    public Arc getArc(int i);

    /**
     * Returns the number of arcs in the model.
     * @return
     */
    public int arcsCount();

    /**
     * Returns an iterator on the <b>outgoing</b> nodes of a given node.
     * Arcs in <code>GraphModel</code> are oriented, outgoing nodes of a node N
     * are all that nodes reachable by following arcs which origin is N.
     *
     * @param n
     * @return
     * @see org.graphnav.model.GraphModel#getIngoingNodes(org.graphnav.swing.Node)
     */
    public Iterator<Node> getOutgoingNodes(Node n);

    /**
     * Returns an iterator on the <b>ingoing</b> nodes of a given node.
     * Arcs in <code>GraphModel</code> are oriented, ingoing nodes of a node N
     * are all that nodes reachable by following arcs which destination is N.
     *
     * @param n
     * @return
     */
    public Iterator<Node> getIngoingNodes(Node n);

    /**
     * Returs the number of outgoing nodes of a given node.
     *
     * @param n the reference node
     * @return a non negative number.
     */
    public int outgoingNodesCount(Node n);

    /**
     * Returns the number of ingoing nodes of a given node.
     *
     * @param n the reference node
     * @return a non negative number.
     */
    public int ingoingNodesCount(Node n);

    /**
     * Returns <code>true</code> if there is an arc going from n1 to n2,
     * <code>false</code> otherwise.
     *
     * @param n1
     * @param n2
     * @return
     */
    public boolean adiacent(Node n1, Node n2);

    /**
     * Adds a <code>GraphModelListener</code> to the model.
     *
     * @param gml the listener to add
     */
    public void addGraphModelListener(GraphModelListener gml);

    /**
     * Removes a  <code>GraphModelListener</code> from the model.
     * If not present do nothing.
     *
     * @param gml  the listener to remove
     */
    public void removeGraphModelListener(GraphModelListener gml);

}
